package lumis.service.wsrp.consumer.doui;

import lumis.doui.control.ControlContainer;
import lumis.doui.control.IControl;
import lumis.doui.control.tabulardata.AdvancedTabularDataControl;
import lumis.doui.source.ISourceData;
import lumis.doui.source.TabularSource;
import lumis.portal.PortalException;
import lumis.portal.manager.ManagerException;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.serviceinterface.IServiceInterfaceUrl;
import lumis.portal.transaction.PortalTransactionFactory;
import lumis.portal.transaction.TransactionRequiredException;
import lumis.service.wsrp.consumer.producermanager.ClonedPortlet;
import lumis.util.XmlUtil;

import java.util.HashMap;
import java.util.Map;

import org.w3c.dom.Node;

/**
 * Control to render a link to a runtime interface in a tabular data control.
 * The <code>runtimeInterfaceId</code> element specifies the id of the runtime
 * interface that must be called.
 * Also, it is possible to specify a set of parameters. For each parameter it
 * is possible to define the parameter name and the field id from which value
 * will be retrieved.
 * The attribute fieldId is required. The attribute name is optional. If it is
 * not specified, the parameter will be set with the same name of the field.
 * 
 * <p>
 * Example of a LinkToRuntimeTabularDataControl definition:
 * <xmp>
 * <runtimeInterfaceId>viewItem</runtimeInterfaceId>
 * <parameters>
 * 	<parameter name="itemId" fieldId="entryId" />
 * </parameters> 
 * </xmp>
 *
 * @version $Revision: 13092 $ $Date: 2011-05-28 18:19:06 -0300 (Sat, 28 May 2011) $
 * @since 6.0.0
 */
public class LinkToRuntimeTabularDataControl extends AdvancedTabularDataControl
{
	/**
	 * Runtime interface id element in control definition.
	 * @since 6.0.0
	 */
	private static String ELEMENT_RUNTIME_INTERFACE_ID = "runtimeInterfaceId";
	
	/**
	 * Parameter element query.
	 * @since 6.0.0
	 */	
	private static String ELEMENT_PARAMETER = "parameters/parameter";
	
	/**
	 * Parameter name attribute name.
	 * @since 6.0.0
	 */
	private static String ATTRIBUTE_NAME = "name";
	
	/**
	 * Field id attribute name.
	 * @since 6.0.0
	 */
	private static String ATTRIBUTE_FIELD_ID = "fieldId";
	
	/**
	 * The runtime interface id.
	 * @since 6.0.0
	 */
	private String runtimeInterfaceId;
	/**
	 * Parameters map where the key is the parameter name and the value is the
	 * field id to retrieve the parameter value.
	 * @since 6.0.0
	 */
	private Map<String, String> parameterMap = new HashMap<String, String>();
	/**
	 * Service id.
	 * @since 6.0.0
	 */	
	private String serviceId;
	/**
	 * Service instance id.
	 * @since 6.0.0
	 */	
	private String serviceInstanceId;
	
	@Override
	public void init(Node controlDefinitionNode,
					ControlContainer controlContainer,
					IControl parentControl)
				throws PortalException
	{
		super.init(controlDefinitionNode, controlContainer, parentControl);
		// reads the control definition
		readDefinition(controlDefinitionNode, controlContainer, parentControl);
	}
	
	/**
	 * Reads the control configuration and sets the control attributes.
	 * @param controlDefinitionNode		the definition node.
	 * @param controlContainer			the control container.
	 * @param parentControl				the parent control.
	 * @throws PortalException			if an error occur reading the definition.
	 * @since 6.0.0
	 */
	protected void readDefinition(Node controlDefinitionNode,
									ControlContainer controlContainer,
									IControl parentControl)
								throws PortalException
	{
		this.serviceId = douiContext.getRequest().getServiceConfig().getId();		
		this.serviceInstanceId = douiContext.getRequest().getServiceInstanceConfig().getId();
				
		Node nodeRuntimeInterface = XmlUtil.selectSingleNode(ELEMENT_RUNTIME_INTERFACE_ID, this.controlDefinitionNode);
		this.runtimeInterfaceId = XmlUtil.getTextContent(nodeRuntimeInterface);
				
		Node[] nodeList = XmlUtil.selectNodes(ELEMENT_PARAMETER, this.controlDefinitionNode);
		for (Node node: nodeList)
		{
			String fieldId = XmlUtil.readAttributeString(ATTRIBUTE_FIELD_ID, node);
			String parameterName = XmlUtil.readAttributeString(ATTRIBUTE_NAME, node);
			
			if ((parameterName == null) ||(parameterName.equals(""))) 
			{
				parameterName = fieldId;
			}
			
			this.parameterMap.put(parameterName, fieldId);
		}
	}
	
	@Override
	protected String getRowOnClick(TabularSource<?> source, ISourceData row,
			String compositePrimaryKey, int rowIndex) throws PortalException
	{
		String portletHandle = row.get("portletHandle", String.class);
		if (ManagerFactory.getEntityManager().find(ClonedPortlet.class, portletHandle) == null)
			return null;

		IServiceInterfaceUrl url = getUrl();
		for (String parameterName : this.parameterMap.keySet())
		{
			String fieldId = this.parameterMap.get(parameterName);
			url.setParameter(parameterName, (String) row.get(fieldId));
		}

		return getOnClickString(url.toString());
	}

	private IServiceInterfaceUrl getUrl()
	{
		IServiceInterfaceUrl url = douiContext.getResponse().createRenderURL();
		url.setRunTimeServiceInstanceId(serviceInstanceId);
		String serviceInterfaceId = serviceId + "." + this.runtimeInterfaceId;
		url.setRunTimeServiceInterfaceId(serviceInterfaceId);
		return url;
	}

	/**
	 * @param url
	 * @return
	 * @throws PortalException
	 * @throws TransactionRequiredException
	 * @throws ManagerException
	 * @since 6.0.0
	 */
	private String getOnClickString(String url) throws PortalException
	{
		String onClickString = "window.open('$url', '', '$properties');";
		String popupWindowProperties = ManagerFactory.getServiceInterfaceManager()
				.getServiceInterfaceConfig(
				serviceId + "." + runtimeInterfaceId,
						PortalTransactionFactory.getCurrentTransaction())
				.getPopupWindowProperties();

		return onClickString.replace("$url", url).replace("$properties", popupWindowProperties);
	}

}
